package com.ruoyi.matrix.util

import com.fasterxml.jackson.annotation.JsonFormat
import com.fasterxml.jackson.core.JsonGenerator
import com.fasterxml.jackson.core.JsonParser
import com.fasterxml.jackson.databind.*
import com.fasterxml.jackson.databind.deser.ContextualDeserializer
import com.fasterxml.jackson.databind.deser.std.StdDeserializer
import com.fasterxml.jackson.databind.ser.ContextualSerializer
import com.fasterxml.jackson.databind.ser.std.StdSerializer
import com.ruoyi.common.utils.ServletUtils
import org.apache.poi.ss.usermodel.Cell
import org.apache.poi.ss.usermodel.CellType
import java.io.IOException
import java.math.BigDecimal
import java.time.ZoneId
import java.time.ZonedDateTime
import java.time.format.DateTimeFormatter
import java.util.*


// BigDecimal的0判断
// 其他情况可以使用 < > 重载
fun BigDecimal?.isZero(): Boolean = this != null && this.compareTo(BigDecimal.ZERO) == 0
fun BigDecimal?.isNotZero(): Boolean = this != null && this.compareTo(BigDecimal.ZERO) != 0
fun BigDecimal?.isNullOrZero(): Boolean = this == null || this.compareTo(BigDecimal.ZERO) == 0

fun parseCell(cell: Cell?): String {
    if (cell == null) return ""

    return when (cell.cellType) {
        // 强制为bigdecimal在转为字符串，避免科学计数法
        CellType.NUMERIC -> cell.numericCellValue.toBigDecimal().toString().trim()
        CellType.STRING -> cell.stringCellValue.trim()
        else -> ""
    }
}

// date序列化和反序列化，根据公参的时区输出（序列化）对应时区的时间，输入（反序列化）时则全部转化为北京时区
// 如果没有公参数（比如非http上下文请求，则取默认时区）
class DynamicTimeZoneDateSerializer protected constructor(t: Class<Date?>? = null) : StdSerializer<Date>(t),
    ContextualSerializer {

    constructor(format: String) : this() {
        this.format = format
    }

    private var format = "yyyy-MM-dd HH:mm:ss"

    override fun createContextual(prov: SerializerProvider?, property: BeanProperty?): JsonSerializer<*> {
        if (property != null) {
            val annFormat = property.getAnnotation(JsonFormat::class.java)
            if (annFormat != null)
                return DynamicTimeZoneDateSerializer(annFormat.pattern)
        }
        return DynamicTimeZoneDateSerializer()
    }

    /** 输出给调用方，一般是界面 */
    @Throws(IOException::class)
    override fun serialize(date: Date, jsonGenerator: JsonGenerator, serializerProvider: SerializerProvider) {
        val tz = ServletUtils.getRequestAttributes().request.getAttribute("tz") as String? ?: ZoneId.systemDefault().id
        val zt = ZonedDateTime.ofInstant(date.toInstant(), ZoneId.of(tz))
        val output = zt.format(DateTimeFormatter.ofPattern(format))
        jsonGenerator.writeString(output)
    }
}

class DynamicTimeZoneDateDeserializer protected constructor(t: Class<Date?>? = null) : StdDeserializer<Date>(t),
    ContextualDeserializer {
    constructor(format: String) : this() {
        this.format = format
    }

    private var format = "yyyy-MM-dd HH:mm:ss"

    override fun createContextual(ctxt: DeserializationContext?, property: BeanProperty?): JsonDeserializer<*> {
        if (property != null) {
            val annFormat = property.getAnnotation(JsonFormat::class.java)
            if (annFormat != null)
                return DynamicTimeZoneDateDeserializer(annFormat.pattern)
        }
        return DynamicTimeZoneDateDeserializer()
    }

    /** 输入，转换为北京时间（系统默认时区） */
    @Throws(IOException::class)
    override fun deserialize(p: JsonParser, ctxt: DeserializationContext?): Date {
        val tz = ServletUtils.getRequestAttributes().request.getAttribute("tz") as String? ?: ZoneId.systemDefault().id
        val input = "${p.text} $tz"
        val inputFormat = DateTimeFormatter.ofPattern("$format VV")
        val zt = ZonedDateTime.parse(input, inputFormat)
        return Date.from(zt.toInstant())
    }
}

fun MutableMap<String, MutableList<String>>.appendError(key: String, value: String) {
    this.putIfAbsent(key, mutableListOf())
    this[key]!!.add(value)
}

fun split2array(value: String): Set<String> {
    val v = value.replace("[\\n\\s,，`;]+".toRegex(), ",")
    val vv = v.split(",".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray()
    val set: MutableSet<String> = HashSet()
    for (s in vv) {
        if (s.isEmpty()) {
            continue
        }
        set.add(s)
    }
    return set
}


fun main() {
    println(ZoneId.systemDefault().id)
    println(BigDecimal(0.000).isZero())
    println(BigDecimal(1).isNotZero())
    println(BigDecimal(1.000).isNotZero())
    println(BigDecimal(0.000).isNotZero())
}